package org.springboot.aop.config;

import java.util.List;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springboot.aop.dto.StudentDTO;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class AOPConfig {

    // 表达式
    // 匹配org.springboot.aop.service包及其子包下的所有类的所有方法
    @Pointcut("execution(* org.springboot.aop.service..*.*(..))")
    public void executeService() {

    }

    /**
     * 前置通知，方法调用前被调用
     * 
     * @param joinPoint
     */
    @Before("executeService()")
    public void doBeforeAdvice(JoinPoint joinPoint) {
        System.out.println("我是前置通知!!!");
        // 获取目标方法的参数信息
        Object[] obj = joinPoint.getArgs();
        for (Object object : obj) {
            System.out.println("参数是:" + object.toString());
        }
    }

    // @After("executeService()")
    // public void doAfterAdvice(JoinPoint joinPoint) {
    // System.out.println("我是后置通知");
    // }

    @After("execution(* org.springboot.aop.service..*.*(..))")
    public void doAfterAdvice(JoinPoint joinPoint) {
        System.out.println("我是后置通知，哈哈哈");
    }

    @SuppressWarnings("unchecked")
    @Around("executeService()")
    public void doAround(ProceedingJoinPoint joinPoint) {
        System.out.println("环绕方法执行之前");
        Object[] objects = joinPoint.getArgs();
        if (null == objects) {
            try {
                joinPoint.proceed(objects);
            } catch (Throwable e) {
                e.printStackTrace();
            }
        } else {
            List<StudentDTO> studentDTOList = (List<StudentDTO>) objects[0];
            // 适用于元素为StudentDTO
            for (StudentDTO studentDTO : studentDTOList) {
                studentDTO.setName(studentDTO.getName() + ":我是尾巴~~");
            }
            try {
                joinPoint.proceed(objects);
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
        System.out.println("环绕方法执行之后");
    }

}
